#ifndef _MB_UTILS_H
#define _MB_UTILS_H

/* ----------------------- Defines ------------------------------------------*/
#include "mbport.h"
#include "mbframe.h"
#include "mbtypes.h"

/*! \brief Rounds an integer number to the next multiple of 2.
 * \internal
 *
 * \param num The number to round.
 */
#define MB_CEIL_2( num ) ( ( ( ( num ) + 1 ) / 2 ) * 2 )

/* \brief Perform integer division where the result is rounded
 *  toward +infinity.
 * \internal
 *
 * \param dividend Divided
 * \param divisor  Divisor
 */
#define MB_INTDIV_CEIL( dividend, divisor ) ( ( ( dividend ) + ( divisor )-1 ) / ( divisor ) )

/* \brief Perform integer division where the result is rounded
 *   toward the nearest integer number.
 * \internal
 *
 * \param dividend Divided
 * \param divisor  Divisor
 */
#define MB_INTDIV_ROUND( dividend, divisor ) ( ( ( dividend ) + ( divisor ) / 2 ) / ( divisor ) )

/* \brief Perform integer division where the result is rounded
 *   toward -infinity.
 * \internal
 *
 * \param dividend Divided
 * \param divisor  Divisor
 */
#define MB_INTDIV_FLOOR( dividend, divisor ) ( ( dividend ) / ( divisor ) )

/*! \brief Wrap around index in ring buffer
 * \internal
 */
#define MB_UTILS_RINGBUFFER_INCREMENT( idx, buffer ) \
    do                                               \
    {                                                \
        idx++;                                       \
        if( idx >= MB_UTILS_NARRSIZE( buffer ) )     \
        {                                            \
            idx = 0;                                 \
        }                                            \
    } while( 0 )

/*! \brief Calculate the number of elements in an array which size is known
 *   at compile time.
 * \internal
 * \param x The array.
 */

#define MB_UTILS_NARRSIZE( x ) ( sizeof( x ) / sizeof( ( x )[0] ) )
/*! \brief Checks if a handle is valid.
 * \internal
 *
 * This method checks if a handle is valid. It uses the ubIdx index to
 * check if the pointer points to a valid handle.
 *
 * \param pxHdl A pointer to a handle.
 * \param arxHdl An array of handles.
 * \return A boolean value.
 */
#define MB_IS_VALID_HDL( pxHdl, arxHdl ) ( ( ( pxHdl ) != NULL ) && ( pxHdl ) == &arxHdl[( pxHdl )->ubIdx] )

/* ----------------------- Type definitions ---------------------------------*/

/* ----------------------- Function prototypes ------------------------------*/
USHORT usGenerateCRC16CheckCode(UBYTE *pubData, UBYTE ubDataLength);
UBYTE ubASCII2HEX( UBYTE ubCharacter );
UBYTE ubHEX2ASCII( UBYTE ubByte );
UBYTE ubGenerateLRCCheckCode( const UBYTE *pubFrame, USHORT usLen );

eMBException eMBErrorcodeToException( eMBErrorCode eCode );
eMBErrorCode eMBExceptionToErrorcode( UBYTE eMBPDUException );

#endif
